package empe;

import javax.xml.parsers.*;// analisadores SAX e DOM
import org.xml.sax.*;// API genérica do SAX
import org.xml.sax.helpers.*;// manipuladores
import java.io.*;

/**
 * Classe importadora de xml
 */
public class XMLimport extends DefaultHandler {

		private static String fileName;
		public int n,m;
		private int[][] matriz;
		private float micro, ro, delta;
		private int tmax;
		private long populacao_init, populacao_max;
		private String ntag;
		private int xact, yact;
		
		

		/**
		 * Detecta novos elementos;
		 * Controla a leitura da matriz (com verificacao de dimensao)
		 * Le atributos dos elementos (quando aplicado)
		 * @param uri unknown
		 * @param name nome do elemento
		 * @param tag nome da tag do elemento
		 * @param atts lista de atributos dos elementos
		 */		
		public void startElement (String uri, String name,
		                         String tag, Attributes atts) 
		{
		    ntag=tag;
		    
//		  ex: <simulacao instfinal = ”100” popinicial = ”10” popmax = ”100” >
		    if(ntag.compareTo("simulacao")==0)
			{
				int num_att=atts.getLength();						
				for(int i=0; i<num_att; i++)
				{
					String novo=atts.getQName(i);
					
					if(novo.compareTo("instfinal")==0)
					{
						try
						{
							tmax=Integer.parseInt(atts.getValue(i));
						}catch(Exception e)
						{
							System.out.print("\nHouve uma excepção ao tentar ler o parametro do instante final: "+e);
							System.exit(2);
						}
					} 
					else if (novo.compareTo("popinicial")==0)
					{
						try
						{
							populacao_init=Integer.parseInt(atts.getValue(i));
						}catch(Exception e)
						{
							System.out.print("\nHouve uma excepção ao tentar ler o parametro da população inicial: "+e);
							System.exit(2);
						}
					}
					else if (novo.compareTo("popmax")==0)
					{
						try
						{
							populacao_max=Integer.parseInt(atts.getValue(i));
						}catch(Exception e)
						{
							System.out.print("\nHouve uma excepção ao tentar ler o parametro da população máxima: "+e);
							System.exit(2);
						}
					}
				}
			} //fim de leitura de atributos de simulacao
		    
//			ex < matriz numlinhas = ”3” numcolunas = ”6” >
		    if(ntag.compareTo("matriz")==0)
		    {
		    	int num_att=atts.getLength();						
				for(int i=0; i<num_att; i++)
				{
					
					String novo=atts.getQName(i);
					
					if(novo.compareTo("numlinhas")==0)
					{
						try
						{
							n=Integer.parseInt(atts.getValue(i), 10);
						}catch(Exception e)
						{
							System.out.print("\nHouve uma excepção ao tentar ler o parametro do numero de linhas: "+e);
							System.exit(2);
						}
					} 
					else if (novo.compareTo("numcolunas")==0)
					{
						try
						{
							m=Integer.parseInt(atts.getValue(i), 10);
						}catch(Exception e)
						{
							System.out.print("\nHouve uma excepção ao tentar ler o parametro do número de linhas: "+e);
							System.exit(2);
						}
					}
					
					if(n!=0 & m!=0)
					{
						matriz=new int[n][m];
					}
				}
		    } //fim de leitura de atributos de matriz
		    
		    //< linha >
		    if(ntag.compareTo("linha")==0)
		    {
		    	if(xact<(m-1) & yact!=-1)
		    	{
		    		System.out.print("\ncolunas a menos\n");
		    		System.exit(2);
		    	}		    		
		    	
		    	yact++;
		    	if (yact==n)
		    	{
		    		System.out.print("\nlinhas a mais\n");
		    		System.exit(2);
		    	}
		    	
		    	xact=-1;
		    }
		    
		    //< coluna > 1 < coluna >
		    if(ntag.compareTo("coluna")==0)
		    {
		    	xact++;
		    	if (xact==m)
		    	{
		    		System.out.print("\ncolunas a mais\n");
		    		System.exit(2);
		    	}
		    }
		    
		    //< morte param = ”10”/ >
		    if(ntag.compareTo("morte")==0)
		    {
		    	try{
		    	micro=Float.parseFloat(atts.getValue(0));
		    	}catch(Exception e)
				{
					System.out.print("\nHouve uma excepção ao tentar ler o parametro da morte: "+e);
					System.exit(2);
				}
		    }
		    //< reproducao param = ”1”/ >
		    if(ntag.compareTo("reproducao")==0)
		    {
		    	try
		    	{
		    	ro=Float.parseFloat(atts.getValue(0));
		    	}catch(Exception e)
				{
					System.out.print("\nHouve uma excepção ao tentar ler o parametro da reprodução: "+e);
					System.exit(2);
				}
		    }
		    //< mutacao param = ”1”/ >
		    if(ntag.compareTo("mutacao")==0)
		    {
		    	try
		    	{
		    	delta=Float.parseFloat(atts.getValue(0));
		    	}catch(Exception e)
				{
					System.out.print("\nHouve uma excepção ao tentar ler o parametro da mutação: "+e);
					System.exit(2);
				}
		    }	    
		}
		
		/**
		 * Le o conteudo da matriz 
		 * (a posicao e controlada pela funcao start element)
		 * @param ch caracteres do conteudo de um elemtento
		 * @param start offset
		 * @param length comprimento da cadeia de caracteres em ch		 
		 */
		public void characters(char[]ch,int start,int length){
		    String novo=new String(ch,start,length);
		    novo=novo.trim();		    
			if(ntag.compareTo("coluna")==0)
			{
				try
				{
					matriz[yact][xact]=Integer.parseInt(novo, 10);
				}catch(Exception e)
				{
					System.out.print("\nHouve uma excepção ao tentar ler valor de matriz: "+e);
					System.exit(2);
				}
				ntag="";
			}
			
		}
		
		/**
		 * Lanca excepcao quando o xml nao respeita o dtd
		 * @param exception excepcao do erro
		 */
		public void error(SAXParseException exception)
		{
			System.out.print("\nerro:" + exception);
			System.exit(2);
		}

		/**
		 * Inicializa o importador do xml e le o ficheiro
		 * @param ficheiro ficheiro xml a ser lido
		 */
		public XMLimport(String ficheiro) throws Exception {
			
			fileName = ficheiro;
			
			//		 cria analisador SAX
			SAXParserFactory fact = SAXParserFactory.newInstance();
			fact.setValidating(true);
			SAXParser saxParser = fact.newSAXParser();
			
			//		 analisa o documento com este manipulador
			DefaultHandler handler = this;
			
			xact=yact=-1;
			
			saxParser.parse(new File(fileName), handler);
			
			if(xact<(m-1) | yact<(n-1))
			{
				System.out.print("\nmatriz imcompleta\n");
				System.exit(2);
			}
			
			//actualizar_controlo();
			
		}
		
		/**
		 * Actualiza a classe controlo com os parametros lidos no xml
		 */
		public void actualizar_controlo()
		{
			Controlo.init(tmax, n, m, matriz, populacao_init, populacao_max, micro, ro, delta);
		}
}
